import { Component, createApp } from 'vue'
import { DirectiveBinding } from '@vue/runtime-core'
import { addClass, getMaxZIndex, removeClass } from '@/utils'

const relativeCls = '_app_relative'

interface LoadingElement extends HTMLElement{
  [propName: string] : any
}
type Position = 'static' | 'absolute' | 'fixed' | 'relative' | 'inherit' | ''
export default function createLoadingLikeDirective(Comp: Component) {
  return {
    mounted(el: LoadingElement, binding: DirectiveBinding) {
      const app = createApp(Comp)
      const instance: any = app.mount(document.createElement('div'))
      const name = Comp.name as string
      if (!el[name]) {
        el[name] = {}
      }
      el[name].instance = instance
      const title = binding.arg
      if (typeof title !== 'undefined') {
        instance.setTitle(title)
      }
      if (binding.value) {
        append(el)
      }
    },
    updated(el: LoadingElement, binding: DirectiveBinding) {
      const title = binding.arg
      const name = Comp.name as string
      if (!el[name]) {
        el[name] = {}
      }
      if (typeof title !== 'undefined') {
        el[name].instance.setTitle(title)
      }
      if (binding.value !== binding.oldValue) {
        binding.value ? append(el) : remove(el)
      }
    }
  }

  function append(el: LoadingElement) {
    const style = getComputedStyle(el)
    const name = Comp.name as string
    if (['absolute', 'fixed', 'relative'].indexOf(style.position) === -1) {
      addClass(el, relativeCls)
    }
    el[name].instance.$el.style.zIndex = (getMaxZIndex() + 1).toString()
    el.appendChild(el[name].instance.$el)
  }

  function remove(el: LoadingElement) {
    const name = Comp.name as string
    removeClass(el, relativeCls)
    el.removeChild(el[name].instance.$el)
  }
}
